package com.kun.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import net.sf.ehcache.CacheManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.servlet.Filter;
@Configuration
public class ShiroConfig {
	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		System.out.println("ShiroConfiguration.shirFilter()");
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		
		//自定义filter
		Map<String, Filter> filters = new LinkedHashMap<>();
		filters.put("roleOrFilter", manyRolesAuthorizationFilter());
		shiroFilterFactoryBean.setFilters(filters);
		
		//拦截器.
		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
		//用户登录拦截
		filterChainDefinitionMap.put("/my", "user");//记住密码可查看
		filterChainDefinitionMap.put("/my/*", "authc");
		filterChainDefinitionMap.put("/admin/index.html", "perms[manageInfo:view]");
		//filterChainDefinitionMap.put("/admin/index.html", "authc,roleOrFilter[super_admin,web_admin,book_admin,admin]");
		//filterChainDefinitionMap.put("/admin/**", "roles[super_admin]");
		
		//个人中心  拦截登录
		filterChainDefinitionMap.put("/comment/review", "user");
		filterChainDefinitionMap.put("/comment/toLike", "user");
		filterChainDefinitionMap.put("/comment/deleteComment", "user");
		//借阅  拦截登录
		filterChainDefinitionMap.put("/borrow/**", "authc");
		
		
		filterChainDefinitionMap.put("/**", "anon");
		
		
		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面      user:edit:*、user:*:*、user:*:manager
		//shiroFilterFactoryBean.setLoginUrl("/login"); 自定义shiroLoginFilter中跳转
		//未授权界面
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	/**
	 * 凭证匹配器（将页面传来的密码加密）
	 * @return
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher(){
		//new HashedCredentialsMatcher();
		HashedCredentialsMatcher hashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher(ehCacheManager());
		hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法
		hashedCredentialsMatcher.setHashIterations(1024);//散列的次数
		return hashedCredentialsMatcher;
	}

	@Bean
	public MyShiroRealm myShiroRealm(){
		MyShiroRealm myShiroRealm = new MyShiroRealm();
		myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myShiroRealm;
	}

	@Bean
	public MySecondRealm mySecondRealm(){
		MySecondRealm mySecondRealm = new MySecondRealm();
		mySecondRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return mySecondRealm;
	}

	@Bean
	public SecurityManager securityManager(){
		DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
		//securityManager.setRealm(myShiroRealm());
		//实现一个realm即可
        securityManager.setAuthenticator(modularRealmAuthenticator());
		//多realm配置
		List<Realm> realms=new ArrayList<>();
        realms.add(myShiroRealm());
        realms.add(mySecondRealm());
        securityManager.setRealms(realms);
		//注入记住我管理器
	    securityManager.setRememberMeManager(rememberMeManager());
	    //注入缓存管理器;  
        securityManager.setCacheManager(ehCacheManager());//这个如果执行多次，也是同样的一个对象; 
		return securityManager;
	}

	
	/**
     * 系统自带的Realm管理，主要针对多realm
     * */
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        ModularRealmAuthenticator modularRealmAuthenticator=new ModularRealmAuthenticator();
        modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthenticator;
    }
    
	/**
	 *  开启shiro aop注解支持.
	 *  使用代理方式;所以需要开启代码支持;
	 * @param securityManager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	@Bean(name="simpleMappingExceptionResolver")
	public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
		SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
		Properties mappings = new Properties();
		mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
		mappings.setProperty("UnauthorizedException","403");
		r.setExceptionMappings(mappings);  // None by default
		r.setDefaultErrorView("error");    // No default
		r.setExceptionAttribute("ex");     // Default is "exception"
		//r.setWarnLogCategory("example.MvcLogger");     // No default
		return r;
	}
	
	
	
	@Bean  
    public EhCacheManager ehCacheManager(){  
      System.out.println("ShiroConfiguration.getEhCacheManager()");  
      CacheManager cacheManager = CacheManager.getCacheManager("es");
      if(cacheManager == null){
          try {
              cacheManager = CacheManager.create(ResourceUtils.getInputStreamForPath("classpath:config/ehcache-shiro.xml"));
          } catch (IOException e) {
              throw new RuntimeException("initialize cacheManager failed");
          }
      }
      EhCacheManager ehCacheManager = new EhCacheManager();
      ehCacheManager.setCacheManager(cacheManager);
      return ehCacheManager;
    }
	
    /**
     * cookie对象;
     * @return
     * */
    @Bean
    public SimpleCookie rememberMeCookie(){
        //System.out.println("ShiroConfiguration.rememberMeCookie()");
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        simpleCookie.setMaxAge(259200);
        return simpleCookie;
    }
    /**
     * cookie管理对象;
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        System.out.println("ShiroConfiguration.rememberMeManager()");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }
    
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
    
    //自定义filter
    @Bean(name = "shiroLoginFilter")
    public ShiroLoginFilter shiroLoginFilter(){
        ShiroLoginFilter shiroLoginFilter = new ShiroLoginFilter();
        return shiroLoginFilter;
    }
    
    //自定义filter
    @Bean(name = "manyRolesAuthorizationFilter")
    public ManyRolesAuthorizationFilter manyRolesAuthorizationFilter(){
    	ManyRolesAuthorizationFilter manyRolesAuthorizationFilter = new ManyRolesAuthorizationFilter();
        return manyRolesAuthorizationFilter;
    }
}